#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# @Project:     py_utils
# @File:        u_module.py
# @Author:      Fan GuiChuan
# @Date:        2024/8/20 14:44
# @Version:     Python3.7
# @Description:
import ast
import importlib
import inspect
import os
import sys

from .u_path import PathManager


class ModuleManager(object):
    """
    模块管理类
    """
    @classmethod
    def get_method_object(cls, method_name, module_object):
        return module_object.__getattribute__(method_name)

    @staticmethod
    def import_module_according_path(module_path: str, raiser_err: bool = False):
        """
        根据模块文件的路径将文件导入为模块
        使用示例：
        _module = ModuleManager.import_module_according_path("/test/test.py")
        _module.func_name(xxx)
        """
        try:
            module_path = PathManager.format_to_linux_path(module_path)
            if PathManager.is_dir(module_path):
                module_name = module_path.replace('/', '.')
            elif PathManager.is_file(module_path):
                module_name = module_path[:-3].replace('/', '.')
            else:
                return None

            return importlib.import_module(module_name)
        except Exception as e:
            if raiser_err:
                raise e
            else:
                return None

    @staticmethod
    def import_method_from_file(method_name: str, module_path: str, raise_err: bool = False):
        """
        根据模块文件的路径导入文件中的某个方法
        使用示例：
        _func = ModuleManager.import_method_from_file('func', '/test/test.py')
        _func()
        """
        try:
            module = ModuleManager.import_module_according_path(module_path)
            return module.__getattribute__(method_name)
        except Exception as e:
            if raise_err:
                raise e
            else:
                return None

    @staticmethod
    def get_class_map(dir_path: str, file_name_suffix: str = "") -> dict:
        """
        获取指定目录下所有python文件中的类，忽略_开头的文件内部类，重名的类只识别一个
        :return: 类字典，格式{类名：文件绝对路径}
        """
        if not PathManager.is_dir(dir_path):
            return {}

        _res = {}
        file_pattern = file_name_suffix + ".py"
        for file in PathManager.file_walk(dir_path, pattern=file_pattern):
            with open(file, "r", encoding="utf-8") as f:
                tree = ast.parse(f.read())
                for node in ast.walk(tree):
                    if not isinstance(node, ast.ClassDef) or node.name.startswith("_"):
                        continue
                    _res[node.name] = file
        return _res

    @staticmethod
    def call_class_method_by_name(cls_obj, method_name: str, **kwargs):
        """

        """
        for func_name, func in inspect.getmembers(cls_obj, inspect.isfunction):
            if func_name == method_name:
                return func(**kwargs)

        for func_name, func in inspect.getmembers(cls_obj, inspect.ismethod):
            if func_name == method_name:
                return func(**kwargs)

        return None

    @staticmethod
    def reload_module(method_obj):
        module_name = sys.modules[method_obj.__module__]
        importlib.reload(module_name)
